﻿namespace FFF.Test.Application.AppServices.PublicService.File
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Text;
    using System.Threading.Tasks;
    using Abp.Application.Services;
    using Abp.Auditing;
    using Abp.EntityFrameworkCore;
    using Abp.Runtime.Caching;
    using Abp.UI;
    using Aliyun.OSS;
    using Aliyun.OSS.Util;
    using Microsoft.AspNetCore.Authorization;
    using Microsoft.AspNetCore.Http;
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.StaticFiles;
    using FFF.Test.Application.AppServices;
    using FFF.Test.Application.PublicService.AppService.File.Dto;
    using FFF.Test.DataAccess.Framework;
    using FFF.Test.Entity;
    using FFF.Test.Util.Consts;
    using FFF.Test.Util.Web;
    using Ydm.Extensions;

    /// <summary>
    /// File的管理对象
    /// </summary>
    [YdmApiVersionAttribute(Version = "My")]
    public class FileAppService : YdmAbpAppServiceBase, IFileAppService
    {
        private readonly ICacheManager _cacheManager;
        private readonly IHttpContextAccessor _httpContext;

        /// <summary>
        /// Initializes a new instance of the <see cref="FileAppService"/> class.
        /// File构造方法
        /// </summary>
        /// <param name="cacheManager">缓存服务</param>
        /// <param name="httpContext">context</param>
        public FileAppService(
            ICacheManager cacheManager,
            IHttpContextAccessor httpContext
            )
        {
            this._cacheManager = cacheManager;
            this._httpContext = httpContext;
        }

        /// <summary>
        /// 文件上传框下载文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>文件</returns>
        [HttpGet]
        public async Task<FileResult> DownFileForUpload(string filePath)
        {
            if (!filePath.StartsWith("/upload"))
            {
                throw new UserFriendlyException("文件路径不合法");
            }

            filePath = Server.MapPath("~/" + filePath);
            if (File.Exists(filePath))
            {
                new FileExtensionContentTypeProvider().TryGetContentType(filePath, out var contentType);
                byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
                FileContentResult returnFile = new FileContentResult(fileBytes, contentType);
                returnFile.FileDownloadName = Path.GetFileName(filePath);
                return returnFile;
            }
            else
            {
                throw new UserFriendlyException("未找到文件");
            }
        }

        /// <summary>
        /// 下载文件
        /// </summary>
        /// <param name="type">文件的类型</param>
        /// <returns>文件</returns>
        [HttpGet]
        public async Task<FileResult> DownFile(string type)
        {
            var filePath = string.Empty;
            var fileDownName = string.Empty;
            switch (type)
            {
                case "SH_Device":
                    fileDownName = "设备导入模板.xlsx";
                    break;
                default:
                    break;
            }

            // 根据表的名称找一次
            if (filePath.IsNullOrEmpty())
            {
                filePath = $@"~\down\ExcelTemplate\{type}.xlsx";
            }

            filePath = Server.MapPath(filePath);
            if (File.Exists(filePath))
            {
                new FileExtensionContentTypeProvider().TryGetContentType(filePath, out var contentType);
                byte[] fileBytes = await File.ReadAllBytesAsync(filePath);
                FileContentResult returnFile = new FileContentResult(fileBytes, contentType);

                if (fileDownName.IsNullOrEmpty())
                {
                    returnFile.FileDownloadName = Path.GetFileName(filePath);
                }
                else
                {
                    returnFile.FileDownloadName = fileDownName;
                }

                return returnFile;
            }
            else
            {
                throw new ArgumentException("未找到文件");
            }
        }

        /// <summary>
        /// 批量上传文件
        /// </summary>
        /// <param name="type">文件的类型</param>
        /// <returns>文件的集合</returns>
        [HttpPost]
        public async Task<List<string>> BatchUploadFile(string type)
        {
            IFormFileCollection files = this._httpContext.HttpContext.Request.Form.Files;
            if (files == null || files.Count == 0)
            {
                throw new UserFriendlyException("文件不存在");
            }

            List<string> filelst = new List<string>();
            foreach (IFormFile file in files)
            {
                string filePath = $@"/upload/{type}/{DateTime.Now.ToString("yyyyMMddssfff")}_{file.FileName}";

                // string path = Server.MapPath("~" + filePath);
                var lastPath = await this.SaveFileAsync(file, filePath);
                filelst.Add(lastPath.Replace("wwwroot", string.Empty));
            }

            return filelst;
        }

        /// <summary>
        /// 上传文件
        /// </summary>
        /// <param name="type">文件的类型</param>
        /// <returns>文件存储的id的值</returns>
        [HttpPost]

        //[Authorize(Roles = "admin")]
        public async Task<UploadFileOutDto> UploadFile(string type)
        {
            IFormFileCollection files = this._httpContext.HttpContext.Request.Form.Files;
            if (files == null || files.Count == 0)
            {
                throw new UserFriendlyException("文件不存在");
            }

            IFormFile file = files[0];
            var lastPath = await this.SaveFileAsync(file, type);
            UploadFileOutDto outDto = new UploadFileOutDto();
            outDto.Path = lastPath;
            return outDto;
        }

        /// <summary>
        /// 删除文件
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>task</returns>
        [HttpPost]
        [Authorize(Roles = "admin")]
        public async Task DeleteFile(string filePath)
        {
            string fileName = Path.GetFileName(filePath);
            await Task.FromResult(fileName);
            this.ValidateFileType(fileName);
            string path = Server.MapPath(@"~" + filePath);
            if (File.Exists(path))
            {
                File.Delete(path);
            }
        }

        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="file">文件</param>
        /// <param name="type">文件类型</param>
        /// <returns>文件路径</returns>
        private async Task<string> SaveFileAsync(IFormFile file, string type)
        {
            this.ValidateFileType(file.FileName);
            string today = DateTime.Now.ToString("yyyyMMdd");
            string filePath = $@"FFF.Test/{type}/{today}/{DateTime.Now.ToString("yyyyMMddssfff")}_{file.FileName}";

            // 走阿里云上传
            if (!string.IsNullOrEmpty(AppConfigConsts.AliAccessKeyId) && !string.IsNullOrEmpty(AppConfigConsts.AliAccessKeySecret))
            {
                var uploadFileBytes = new byte[file.Length];
                file.OpenReadStream().Read(uploadFileBytes, 0, (int)file.Length);

                using (MemoryStream fileStream = new MemoryStream(uploadFileBytes))
                {
                    var uploadFileName = file.FileName;
                    string md5 = OssUtils.ComputeContentMd5(fileStream, uploadFileBytes.Length);

                    OssClient client = new OssClient($"oss-cn-{AppConfigConsts.AliEndpoint}.aliyuncs.com", AppConfigConsts.AliAccessKeyId, AppConfigConsts.AliAccessKeySecret);

                    //将文件md5值赋值给meat头信息，服务器验证文件MD5  
                    var objectMeta = new ObjectMetadata
                    {
                        ContentMd5 = md5,
                    };

                    // 文件上传--空间名、文件保存路径、文件流、meta头信息(文件md5) //返回meta头信息(文件md5)  
                    client.PutObject(AppConfigConsts.AliBucketName, filePath, fileStream, objectMeta);
                    var fullPath = $"https://{AppConfigConsts.AliBucketName}.oss-cn-{AppConfigConsts.AliEndpoint}.aliyuncs.com/{filePath}";
                    return fullPath;
                }
            }
            else
            {
                var path = Server.MapPath(@"~/" + filePath);
                string dir = Path.GetDirectoryName(filePath);
                if (!Directory.Exists(dir))
                {
                    Directory.CreateDirectory(dir);
                }

                using (FileStream stream = new FileStream(filePath, FileMode.Create))
                {
                    await file.CopyToAsync(stream);
                }

                return filePath;
            }
        }

        private void ValidateFileType(string fileName)
        {
            bool isExistsAllowEx = false; // 是否在允许的扩展名中
            foreach (string key in AppConfigConsts.FileTypes.Keys)
            {
                if (Path.GetExtension(fileName) == key)
                {
                    isExistsAllowEx = true;
                    break;
                }
            }

            if (!isExistsAllowEx)
            {
                throw new UserFriendlyException("文件扩展名称不合法");
            }
        }
    }
}